<?php

declare(strict_types=1);

namespace Common\Middleware\Http;

use Common\Helpers\DebugHelper;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\HttpServer\Router\Dispatched;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

/**
 * 接口请求校验中间件
 */
class ApiMiddleware implements MiddlewareInterface
{
    protected ContainerInterface $container;

    protected RequestInterface $request;

    protected HttpResponse $response;
    public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
    {
        $this->container = $container;
        $this->response = $response;
        $this->request = $request;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (empty($request->getAttribute(Dispatched::class)->handler)){
            return $this->response->json([
                'code' => 401,
                'message' => '非法请求',
                'data' => [
                    'url' => $request->getUri()->getPath(),
                    'project_sn' => $this->request->route('project_sn')
                ]
            ]);
        }
        $callback = $request->getAttribute(Dispatched::class)->handler->callback;

        DebugHelper::consoleWrite('接口处理开始1', [
            'callback'=> $callback,
            'Args'=> $this->request->getParsedBody(),
            'method'=> $request->getMethod()
        ]);
        [$class,$action] = $callback;
        $controller = new $class($this->request, $this->response);
        DebugHelper::consoleWrite('接口action处理', [
            'controller' => $controller,
            'action'=> $action,
            'class'=> $class
        ]);
        /**
         * 检查签名属性是否存在
         */
        //为空都需要，在列表排除
        if (property_exists($controller, 'signOptional') && (empty($controller->signOptional) || !in_array($action, $controller->signOptional))) {
            $request = $request->withAttribute('signOptional', true);
            $Args = $this->request->getParsedBody();
            if (empty($Args['app_id'])){
                return $this->response->json(
                    [
                        'code' => 405,
                        'message' => '请传入app_id',
                        'data' => []
                    ]
                );
            }
        }else{
            /**
             * 写入上下文标记，下一个中间件可以获取到
             */
            $request = $request->withAttribute('signOptional', false);
        }

        /**
         * 根据$authOptional 判断是否需要token验证
         */
        if (property_exists($controller, 'authOptional') && (empty($controller->authOptional) || !in_array($action, $controller->authOptional))) {
            $request = $request->withAttribute('authOptional', true);
            /**
             * 判断头部是否携带token
             */
            $token = $this->request->getHeader('access-token');
            if (empty($token)){
                return $this->response->json(
                    [
                        'code' => 405,
                        'message' => '请传入token',
                        'data' => []
                    ]
                );
            }
        }else{
            /**
             * 写入上下文标记，下一个中间件可以获取到
             */
            $request = $request->withAttribute('authOptional', false);
        }
        return $handler->handle($request);
    }

}
